Building a Complex Tree with Grid-in-Grid
Jumper Chen, Engineer, Potix Corporation
September 1, 2009
ZK 3.6.0 and above
Introduction
A few days ago, we helped a customer to implement a complex tree. He wants the tree to be able to contain a complex table, including paging, header, footer, sorting and so on. It is costly to implement one from scratch, or to extend from the tree component. However, instead of having different components for different purposes, we design ZK components like Lego -- you can put almost any component inside almost any component. In this case, we can build the complex tree by embedding grid inside a grid recursively. To make it more interesting, we also embed a chart inside a grid.
Live Demo
Here is a screen cast of the sample that we use the master-detail grid to implement the complex tree.
An Example of Complex Tree Table
Here is some fragment code from the live demo which we separated into three zul files.
- index.zul the main page.
<grid fixedLayout="true">
<columns>
<column width="25px" />
<column label="Stock Name"/>
<column label="Date"/>
<column label="Open" align="center" sort="auto"/>
<column label="High" align="center" sort="auto"/>
<column label="Low" align="center" sort="auto"/>
<column label="Close" align="center" sort="auto"/>
<column label="volume" align="center" sort="auto"/>
</columns>
<rows>
<row forEach="${stocks}">
<detail open="false" fulfill="onOpen=season.zul"/>
<label value="${stocks[forEachStatus.index]}"/>
<label value="31-Aug-09"/>
<label style="color:red;" onCreate='self.value = nextPrice()'/>
<label onCreate='self.value = nextPrice()'/>
<label style="color:red;" onCreate='self.value = nextPrice()'/>
<label onCreate='self.value = nextPrice()'/>
<label onCreate='self.value = random.nextInt(65536)+ ""'/>
</row>
</rows>
</grid>
- season.zul the second level grid.
<grid fixedLayout="true" oddRowSclass="myinner" onCreate='self.sclass = color[index]'>
<columns>
<column width="25px" />
<column width="35px" >
<checkbox/>
</column>
<column label="Season"/>
<column label="High" align="center" sort="auto"/>
<column label="Low" align="center" sort="auto"/>
<column label="volume" align="center" />
</columns>
<rows>
<row forEach="1,2,3,4">
<detail open="false" fulfill="onOpen=month.zul"/>
<checkbox label="" width="35px" />
<label value="Q-${forEachStatus.index + 1}"/>
<label onCreate='self.value = nextPrice()'/>
<label onCreate='self.value = nextPrice()'/>
<label onCreate='self.value = random.nextInt(655360)+ ""'/>
</row>
</rows>
<foot>
<footer width="25px"/>
<footer label="Avg:" />
<footer/>
<footer onCreate='self.label = nextPrice()' />
<footer onCreate='self.label = nextPrice()' />
<footer onCreate='self.label = random.nextInt(655360) + ""' />
</foot>
</grid>
- month.zul the last level grid.
<grid fixedLayout="true" sclass="blue" oddRowSclass="myinner">
<columns>
<column label="Month"/>
<column label="High" align="center" sort="auto"/>
<column label="Low" align="center" sort="auto"/>
<column label="volume" align="center" />
</columns>
<rows>
<row sclass="last" forEach="1,2,3">
<label value="${months[forEachStatus.index + season]}" />
<label onCreate='self.value = nextPrice()'/>
<label onCreate='self.value = nextPrice()'/>
<label onCreate='self.value = random.nextInt(655360)+ ""'/>
</row>
</rows>
</grid>
As you can see, we use the fulfill mechanism to fill the content of each level and use the detail to make it similar to tree styling.
Download
The application could be downloaded here.
Summary
As shown above, ZK components are like lego. You can mash them up to fulfill a very different purpose. For your own practice, you might try to encapsulate the example here as a macro component to simplify the use further.
Copyright © Jumper Chen. This article is licensed under GNU Free Documentation License. |